#pragma once
#include <cuda_runtime.h>
#include <glm/glm.hpp>

namespace PhysLeo {

/**
 * static peridynamic neohookean material.
 * \f$ h=A_1, g=log^2(x) , G=1\f$.
 */
template<typename T>
class PdmNeohookean {
public:
    /**
    * g function in Pdm Neohookean material is \f$ g=log^2(x)\f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
	__host__ __device__ static T gFunction(T x, T* ptr_material)
	{
        auto logx = log(x);
        return logx * logx;
	}

    /**
    * h function in Pdm Neohookean material is \f$ A_1(x) = \frac{x^2-2log(x)-1}{2} \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T hFunction(T x, T* ptr_material)
    {
        return 0.5f *x*x - log(x) - 0.5f;
    }

    /**
    * first derivative of g function in Pdm Neohookean material is \f$ \frac{2log(x)}{x} \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
	__host__ __device__ static T dgFunction(T x, T* ptr_material)
	{
        auto logx = log(x);
        return 2 * logx / x;
	}

    /**
    * first derivative of h function in Pdm Neohookean material is \f$ x-\frac{1}{x} \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T dhFunction(T x, T* ptr_material)
    {
        return x - 1.0f / x;
    }

    /**
    * first derivative of g function in Pdm Neohookean material is \f$ \frac{2(1-log(x))}{x^2} \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
	__host__ __device__ static T ddgFunction(T x, T* ptr_material)
	{
        return 2.0f / (x*x)*(1 - log(x));
	}

    /**
    * first derivative of h function in Pdm Neohookean material is \f$ 1+\frac{1}{x^2} \f$
    * @param[in] x  a T value describe the deformation severity
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T ddhFunction(T x, T* ptr_material)
    {
        return 1.0f + 1.0f / x / x;
    }

    /**
    * anisotropic function for Pdm Neohookean material, it is isotropic.
    * @param[in] dir  bond direction in material space
    * @param[in] ptr_material  a pointer to vertex specific material data
    * @return T value
    */
    __host__ __device__ static T anisoWeight(glm::tvec3<T> dir, T* ptr_material)
	{
        return 1.0f;
	}
};

}